import BasicConfig from "@/utils/config";
import { formatToken, tansParams } from "./tool";
import { useUserStore } from "@/store/modules/user";
import errorCode from "./errorCode";
import { apiUrl } from "../env";
import {
  useGetRefreshTokenStorage,
  useGetTokenStorage,
} from "../../hooks/useStorage";
import { useRefreshToken } from "../../hooks/useLogin";
import http from "@/utils/http/hub";
import { eventBus } from "../../enums/eventBus";
import encrypt from "../encrypt";
/**
 * 请求池
 * 保存上一次请求,如果token过期,无感刷新token后再次请求
 */
const RequestPool = [];
const _fnSetPool = (config) => {
  const index = RequestPool.findIndex(
    (r) => r.url === config.url && config.custom.auth
  );
  if (index < 0) {
    RequestPool.push(config);
  }
  // console.log("填充 RequestPool~~~", uni.$u.deepClone(RequestPool));
};
const _fnRequestAgain = async (config) => {
  const currentConfig = RequestPool.find((r) => r.url === config.url);
  if (currentConfig) {
    const { url, custom, method, data, params } = currentConfig;
    await useRefreshToken();
    console.log("刷新token后参数", method, params, data);
    return new Promise(async (resolve) => {
      const newData = await http[method.toLowerCase()]({
        url,
        params: method === "POST" ? data : params,
        config: {
          custom,
        },
      });
      resolve(newData);
    });
  }
};
let requestData = null;
const config = (vm) => {
  // 初始化请求配置
  uni.$u.http.setConfig((config) => {
    /* config 为默认全局配置*/
    config.baseURL = apiUrl;
    return config;
  });
  // 请求拦截
  uni.$u.http.interceptors.request.use(
    (config) => {
      console.log("请求拦截", config);
      const token = useGetTokenStorage();
      if (config && config.custom) {
        const {
          loading,
          auth,
          postMountParams,
          refreshToken = true,
        } = config.custom;
        if (loading) {
          BasicConfig.loadToast("加载中");
        }
        // debugger
        if (auth) {
          config.header.Authorization = formatToken(token, config.custom);
          // config.header.access_token = formatToken(token, config.custom);
        }
        if (postMountParams) {
          config.url = `${config.url}?${tansParams(config.data)}`;
        }
      }
      // 初始化请求拦截器时，会执行此方法，此时data为undefined，赋予默认{}
      config.data = config.data || {};
      requestData = config.data;
      // const { sign, timestamp } = encrypt(
      //   `/api${config.url}`,
      //   config.method === "GET" ? config.params : config.data
      // );
      const { sign, timestamp, nonce } = encrypt(
        `/api${config.url}`,
        config.data,
        config.method.toLocaleLowerCase()
      );
      // console.log("encrypt", sign, timestamp);
      config.header.sign = sign;
      config.header.timestamp = timestamp;
      config.header.nonce = nonce;
      config.header.device = "douyin";
      config.header.mode = "user";
      // config.header.recommendation = "";
      _fnSetPool(config);
      // console.log("请求拦截", config);
      return config;
    },
    (config) => {
      // 可使用async await 做异步操作
      return Promise.reject(config);
    }
  );
  let failCode = null;
  // 响应拦截
  uni.$u.http.interceptors.response.use(
    async (response) => {
      console.log("响应拦截", response);
      /* 对响应成功做点什么 可使用async await 做异步操作*/
      if (response.config?.custom?.loading) {
        uni.hideLoading();
      }
      let data = response.data;
      // 自定义参数
      const custom = response.config?.custom;
      // console.log("RequestPool~~~1", uni.$u.deepClone(RequestPool));
      if (data.code !== errorCode.overToken) {
        const index = RequestPool.findIndex(
          (r) => r.url === response.config.url
        );
        RequestPool.splice(index, 1);
      }
      // token过期 无感刷新token
      if (data.code === errorCode.overToken) {
        const oldToken = useGetTokenStorage();
        console.log("token过期.........oldToken:", oldToken);
        failCode = errorCode.overToken;
        if (!oldToken) {
          console.log("!!oldToken uni.$emit");
          uni.$emit(
            eventBus.login.popup,
            true,
            "请求拦截~overToken !!oldToken"
          );
        } else {
          data = await _fnRequestAgain(response.config);
        }
      } else if (data.code === errorCode.reset) {
        uni.$emit(eventBus.login.popup, true, "请求拦截~overToken !!oldToken");
      } else if (data.code !== errorCode.success) {
        if (data.code === errorCode.freeze) {
          uni.showModal({
            title: "提示",
            content: data.message || data.msg,
            showCancel: false,
            confirmText: "知道了",
            confirmColor: BasicConfig.MainColor,
            success: () => {
              uni.switchTab({
                url: "/pages/index/index",
              });
            },
          });
          return new Promise(() => {});
        }
        // 如果没有显式定义custom的toast参数为false的话，默认对报错进行toast弹出提示
        if (custom.toast !== false) {
          // uni.$u.toast(data.message || data.msg);
          BasicConfig.toast(data.message || data.msg);
        }
        // 如果需要catch返回，则进行reject
        if (custom?.catch) {
          // return Promise.reject(data);
          return Promise.resolve(data);
        } else {
          // 否则返回一个pending中的promise，请求不会进入catch中
          return new Promise(() => {});
        }
      }
      // console.log("RequestPool~~~2", uni.$u.deepClone(RequestPool));
      return data ?? {};
    },
    (response) => {
      // console.log("catch", response);
      if (response.config?.custom?.loading) {
        uni.hideLoading();
      }
      const oldToken = useGetTokenStorage();
      if (failCode === errorCode.overToken && !oldToken) {
        uni.$emit(eventBus.login.popup, true, "请求拦截~catch");
      }

      // 对响应错误做点什么 （statusCode !== 200）
      return Promise.reject(response);
    }
  );
};

export default config;
